package com.zyc.studentstudy.utils

import android.text.TextUtils
import timber.log.Timber
import java.io.BufferedReader
import java.io.BufferedWriter
import java.io.Closeable
import java.io.File
import java.io.FileInputStream
import java.io.FileOutputStream
import java.io.FileReader
import java.io.IOException
import java.io.OutputStreamWriter

/**
 * Created by zhangyuncai on 2023/1/4.
 * 文件操作类
 */
object FileUtil {

    private const val TAG = "FileUtil"

    /**
     * 提取File内容转字符串输出
     *
     * @param file 文件对象
     * @return 文件内容的行列表
     */
    @JvmStatic
    fun fileToLines(file: File?): List<String> {
        val lines = mutableListOf<String>()
        if (file != null && file.exists()) {
            Timber.i("exists")
            var reader: BufferedReader? = null
            try {
                reader = BufferedReader(FileReader(file))
                var line: String?
                while (reader.readLine().also { line = it } != null) {
                    line?.let { lines.add(it) }
                }
            } catch (e: Exception) {
                e.printStackTrace()
            } finally {
                reader?.closeQuietly()
            }
        } else {
            Timber.i("no file")
        }
        return lines
    }

    /**
     * 提取File内容转字符串输出
     *
     * @param file 文件对象
     * @return 文件内容的字符串
     */
    @JvmStatic
    fun fileToString(file: File?): String {
        val stringBuilder = StringBuilder()
        if (file != null && file.exists()) {
            var reader: BufferedReader? = null
            try {
                reader = BufferedReader(FileReader(file))
                var line: String?
                while (reader.readLine().also { line = it } != null) {
                    stringBuilder.append(line)
                }
            } catch (e: Exception) {
                e.printStackTrace()
            } finally {
                reader?.closeQuietly()
            }
        }
        return stringBuilder.toString()
    }

    /**
     * 将对象以Json格式排版保存到文件中
     *
     * @param file 文件对象
     * @param json JSON字符串
     * @return 是否保存成功
     */
    @JvmStatic
    fun layoutJsonToFile(file: File, json: String): Boolean {
        return stringToFile(file, JsonUtil.layoutJson(json))
    }

    /**
     * 将字符串保存到文件中
     *
     * @param file 文件对象
     * @param string 字符串内容
     * @return 是否保存成功
     */
    @JvmStatic
    fun stringToFile(file: File, string: String): Boolean {
        return stringToFile(file, string, null)
    }

    /**
     * 将字符串保存到文件中
     *
     * @param file 文件对象
     * @param string 字符串内容
     * @param charsetName 字符集名称
     * @return 是否保存成功
     */
    @JvmStatic
    fun stringToFile(file: File, string: String, charsetName: String?): Boolean {
        if (file.exists()) {
            file.delete()
        }

        var writer: BufferedWriter? = null
        return try {
            file.createNewFile()
            val outputStreamWriter = if (!TextUtils.isEmpty(charsetName)) {
                OutputStreamWriter(FileOutputStream(file), charsetName)
            } else {
                OutputStreamWriter(FileOutputStream(file))
            }
            writer = BufferedWriter(outputStreamWriter)
            writer.write(string)
            writer.flush()
            true
        } catch (e: Exception) {
            e.printStackTrace()
            false
        } finally {
            writer?.closeQuietly()
        }
    }

    /**
     * 删除文件夹或者删除文件
     *
     * @param file 文件或文件夹对象
     */
    @JvmStatic
    fun deleteFolder(file: File) {
        if (!file.exists()) return

        if (file.isDirectory) {
            val files = file.listFiles()
            if (!files.isNullOrEmpty()) {
                for (childFile in files) {
                    deleteFolder(childFile)
                }
            }
        }
        file.delete()
    }

    /**
     * 复制文件
     *
     * @param copyFile 要复制的文件
     * @param copyFileName 复制后的文件名称
     * @param targetDirectory 复制的目的地文件夹
     */
    @JvmStatic
    fun copyFile(copyFile: File?, copyFileName: String, targetDirectory: File?) {
        if (targetDirectory == null || copyFile == null || !copyFile.exists()) return

        if (targetDirectory.exists() && !targetDirectory.isDirectory) return

        if (!targetDirectory.exists()) {
            targetDirectory.mkdirs()
        }

        if (copyFile.isFile) {
            val targetFile = File(targetDirectory, copyFileName)
            try {
                FileInputStream(copyFile).channel.use { inputChannel ->
                    FileOutputStream(targetFile).channel.use { outputChannel ->
                        outputChannel.transferFrom(inputChannel, 0, inputChannel.size())
                    }
                }
            } catch (e: IOException) {
                e.printStackTrace()
            }
        }
    }

    /**
     * 复制文件夹
     *
     * @param copyFile 要复制的文件或文件夹
     * @param targetDirectory 复制的目的地文件夹
     */
    @JvmStatic
    fun copyFolder(copyFile: File?, targetDirectory: File?) {
        if (targetDirectory == null || copyFile == null || !copyFile.exists()) return

        if (targetDirectory.exists() && !targetDirectory.isDirectory) return

        if (!targetDirectory.exists()) {
            targetDirectory.mkdirs()
        }

        if (copyFile.isFile) {
            val targetFile = File(targetDirectory, copyFile.name)
            try {
                FileInputStream(copyFile).channel.use { inputChannel ->
                    FileOutputStream(targetFile).channel.use { outputChannel ->
                        outputChannel.transferFrom(inputChannel, 0, inputChannel.size())
                    }
                }
            } catch (e: IOException) {
                e.printStackTrace()
            }
        } else if (copyFile.isDirectory) {
            val targetFile = File(targetDirectory, copyFile.name)
            targetFile.mkdir()
            val files = copyFile.listFiles()
            if (!files.isNullOrEmpty()) {
                for (file in files) {
                    copyFolder(file, targetFile)
                }
            }
        }
    }

    /**
     * 递归计算文件夹大小
     *
     * @param file 文件夹或文件对象
     * @return 文件夹大小（字节）
     */
    @JvmStatic
    fun getFileSize(file: File): Long {
        if (file.isFile && file.exists()) return file.length()

        var size = 0L
        val files = file.listFiles()
        if (!files.isNullOrEmpty()) {
            for (childFile in files) {
                size += if (childFile.isFile) {
                    childFile.length()
                } else {
                    getFileSize(childFile)
                }
            }
        }
        return size
    }

    /**
     * 递归获取文件或文件夹内的所有文件路径
     *
     * @param file 文件夹或文件对象
     * @param lineList 存储文件路径的列表
     */
    @JvmStatic
    fun getFilesPath(file: File, lineList: MutableList<String>) {
        if (file.exists()) {
            if (file.isFile) {
                lineList.add(file.absolutePath)
            } else if (file.isDirectory) {
                val files = file.listFiles()
                if (!files.isNullOrEmpty()) {
                    for (childFile in files) {
                        getFilesPath(childFile, lineList)
                    }
                }
            }
        }
    }

    /**
     * 获取该文件夹下一级子文件
     *
     * @param file 文件夹对象
     * @param lineList 存储文件路径的列表
     */
    @JvmStatic
    fun getOneFilesPath(file: File, lineList: MutableList<String>) {
        val files = file.listFiles()
        if (!files.isNullOrEmpty()) {
            for (childFile in files) {
                lineList.add("${childFile.absolutePath} ${getFileSize(childFile)}")
            }
        }
    }

    /**
     * 扩展方法：关闭流并忽略异常
     */
    @JvmStatic
    private fun Closeable?.closeQuietly() {
        try {
            this?.close()
        } catch (e: IOException) {
            e.printStackTrace()
        }
    }
}